package com.hailiao.beidou.message.data.message

import com.d10ng.common.base.toByteArrayFromHex
import com.d10ng.common.calculate.isOnlyCode
import com.d10ng.common.transform.decodeGBK
import com.d10ng.datelib.curTime
import com.d10ng.datelib.toLocalDate
import com.hailiao.beidou.core.BDCore
import com.hailiao.beidou.message.bd.constant.TextType
import com.hailiao.beidou.message.data.chat.ChatRepository
import com.hailiao.beidou.message.data.db.DB
import com.hailiao.beidou.message.data.db.constant.SendStatus
import com.hailiao.beidou.message.data.db.entity.MessageEntity
import com.hailiao.beidou.standard2.BDTXR_Data
import com.hailiao.beidou.standard2.BDWAA_Data
import com.hailiao.beidou.standard3.BDEPI_Data
import com.hailiao.beidou.standard3.BDTCI_Data
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

/**
 * 消息接收器
 * @Author d10ng
 * @Date 2024/3/6 13:33
 */
object MessageReceiver {

    private val messageDao by lazy { DB.instant.messageDao() }
    private val contactDao by lazy { DB.instant.contactDao() }
    private val scope = CoroutineScope(Dispatchers.IO)

    init {
        scope.launch {
            BDCore.receiveProtoSharedFlow.collect {
                when(val data = it.protocol) {
                    is BDTCI_Data -> onReceiveMessage(data)
                    is BDTXR_Data -> onReceiveMessage(data)
                    is BDWAA_Data -> onReceiveMessage(data)
                    is BDEPI_Data -> onReceiveMessage(data)
                }
            }
        }
    }

    /**
     * 启动
     */
    @Synchronized
    fun start() {
        println("消息接收器已启动")
    }

    /**
     * 获取消息中的内容
     * @param type TXA_Type
     * @param content String
     * @return String
     */
    private fun getBeanContent(type: TextType, content: String): String {
        return when (type) {
            TextType.MIX -> {
                val temp = if (content.startsWith("A4", true))
                    content.substring(2)
                else content
                if (temp.isOnlyCode())
                    temp.toByteArrayFromHex().decodeGBK()
                else temp
            }
            TextType.CODE -> {
                // 兼容北三设备收到混编数据，但是标记为代码模式的问题 TODO 暂时不清楚是否为个例，使用联参双向卡时配合H3411设备能够复现
                if (content.isOnlyCode() && content.startsWith("A4", true))
                    content.substring(2).toByteArrayFromHex().decodeGBK()
                else content
            }
            else -> content
        }
    }

    /**
     * 处理接收消息
     * @param bean BDTCI_Bean
     * @return MessageEntity
     */
    private suspend fun onReceiveMessage(bean: BDTCI_Data): MessageEntity {
        val content = getBeanContent(TextType.parse3(bean.codeType), bean.content)
        val sendCard = bean.sendAddress.toInt().toString()
        val contact = contactDao.susQueryLike(sendCard).find { it.number.toInt() == sendCard.toInt() }
        val time = curTime
        val message = MessageEntity(
            number = contact?.number ?: bean.sendAddress,
            createTime = time,
            sendTime = time,
            isSendOut = false,
            status = SendStatus.SUCCESS.value,
            content = content,
            isLocation = false,
            location = null
        )
        val id = messageDao.insert(message)
        message.id = id
        ChatRepository.updateBy(message)
        return message
    }

    /**
     * 处理接收消息
     * @param bean BDTXR_Data
     * @return MessageEntity
     */
    private suspend fun onReceiveMessage(bean: BDTXR_Data): MessageEntity {
        val content = getBeanContent(TextType.parse2(bean.type), bean.content)
        val time = curTime
        val message = MessageEntity(
            number = bean.senderAddress,
            createTime = time,
            sendTime = time,
            isSendOut = false,
            status = SendStatus.SUCCESS.value,
            content = content,
            isLocation = false,
            location = null
        )
        val id = messageDao.insert(message)
        message.id = id
        ChatRepository.updateBy(message)
        return message
    }

    /**
     * 插入定位消息
     * @param bean BDWAA_Data
     * @return MessageEntity
     */
    private suspend fun onReceiveMessage(bean: BDWAA_Data): MessageEntity {
        val time = bean.timestamp.toLocalDate()
        val message = MessageEntity(
            number = bean.receiverAddress,
            createTime = time,
            sendTime = time,
            isSendOut = false,
            status = SendStatus.SUCCESS.value,
            content = "[位置消息]",
            isLocation = true,
            location = MessageEntity.Location(
                bean.latitude,
                bean.longitude,
                bean.altitude
            )
        )
        val id = messageDao.insert(message)
        message.id = id
        ChatRepository.updateBy(message)
        return message
    }

    /**
     * 插入定位消息
     * @param bean BDEPI_Data
     * @return MessageEntity
     */
    private suspend fun onReceiveMessage(bean: BDEPI_Data): MessageEntity {
        val time = bean.timestamp
        val sendCard = bean.sendAddress.toInt().toString()
        val contact = contactDao.susQueryLike(sendCard).find { it.number.toInt() == sendCard.toInt() }
        val message = MessageEntity(
            number = contact?.number ?: bean.sendAddress,
            createTime = time,
            sendTime = time,
            isSendOut = false,
            status = SendStatus.SUCCESS.value,
            content = "[位置消息]",
            isLocation = true,
            location = MessageEntity.Location(
                bean.latitude,
                bean.longitude,
                bean.altitude
            )
        )
        val id = messageDao.insert(message)
        message.id = id
        ChatRepository.updateBy(message)
        return message
    }
}